home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / Documentation / Add-On Docs / Brian's Extensions next >
Encoding:
Text File  |  2000-10-06  |  13.9 KB  |  244 lines  |  [TEXT/ttxt]

  1. Brian's Extensions Read Me and Documentation
  2.  
  3. Brian Roddy (roddy@morpheus.xo.com)
  4. 7/16/97
  5.  
  6. In the SpriteWorld files->Utils->Brian's Extensions folder are some free extensions to SpriteWorld that I've been working on in my free time.  They allow sprites which are translucent, scaled or rotated.   There are also files for doing several different kinds of lighting effects.  Each file has fairly extensive comments and documentation.  In general, each file has general documentation at the top and function specific documentation with the functions.   They have been tested to work with 68K and PowerPC Macintoshes, and have been optimized in some cases with PowerPC assembly code.  They work in 8-Bit or 16-Bit color (i.e. 256 colors or Thousands of Colors).
  7.  
  8. To use these, you simply include the files in your project file.   
  9.  
  10. Also note that translucency, scaling and rotation cannot be combined.  That is, you can't have a scaled translucent sprite.  Although this wouldn't be to hard for the avid programmer.  The blitters are fairly well commented.
  11.  
  12. In addition, none of these extensions were designed to work in a scrolling world. You can try to get them to work in a scrolling game, but there are no guarantees that they will work. Generally, any functions that don't work right when clipping is used won't work properly in a scrolling world. (Such as scaling and rotating.) Translucency and other lighting effects might work in a scrolling game, but haven't been tested.
  13.  
  14. The Extended Sprite Test shows how all of this functionality except the tinting works.  The Lighting Demo shows how tinting works.  Lit Breakout is a more detailed example of the LightingSquares functionality.  All demos and code has been built and tested with Think C 6.0, CodeWarrior 10, and CodeWarrior Pro 5. The demos are not included in the main SpriteWorld package, but are included in the SpriteWorld Extra Demos package.
  15.  
  16. Below I've copied sections from the top of each source file so you can see the basic documentation all in this one file:
  17.  
  18. -----------------------------------------------------------------------------
  19.  
  20. BlitPixieScaled.c
  21.  
  22. These routines are blitters that dynamically shrink or stretch the sprite. These 
  23. routines work in 8-bits, 16-bits, and 32-bits.
  24.  
  25. Use SWSetSpriteScaledSize to set the scaling size.  When the sprite is drawn, it
  26. will be stretched or shrunk to the new width and height you specify.  
  27. SWSetSpriteScaledSize takes a sprite pointer and a width and a height.  e.g.:
  28.  
  29. SWSetSpriteScaledSize(mySpritePtr, 20, 50);  // Scale it
  30.  
  31. Use a width or height <= 0 to turn off scaling.  Note that just resetting 
  32. the sprite's draw procedure will not turn off scaling properly.  Make sure to 
  33. call SWSetSpriteScaledSize with a negative width or height.  e.g.:
  34.  
  35. SWSetSpriteScaledSize(mySpritePtr, -1, -1);  // Reset it back to normal
  36.  
  37. The maximum scaled width is 1280. Values larger than this are permissible as long as the Sprite
  38. is clipped so that the visible portion of the Sprite after being clipped is no larger than 1280.
  39. For instance, if your SpriteWorld's window is 1280 pixels wide and your Sprites are clipped
  40. to that window, then your may scale your Sprites larger than 1280 pixels. Otherwise, you will
  41. get an assertion error if you try to scale them larger. You can get around this limitation
  42. if necessary; simply change the definition of kMaxScaledWidth at the beginning of 
  43. BlitPixieScaled.c to any value, and your Sprites can then be scaled to that maximum size.
  44. There is no maximum scaled height; your height can be any size.
  45.  
  46. Also note that scaling is done while drawing to the screen.  As a result, the
  47. pixels in the frames don't match what shows up on the screen.  This means that 
  48. functions which rely on the sprite's mask, such as SWPixelCollision, won't work as 
  49. expected.  Thus using the pixel or mask collision routines with scaled sprites 
  50. won't work accurately.
  51.  
  52. SWSetSpriteScaledSize sets the scaling DrawProc for you automatically, so you don't 
  53. need to call SWSetSpriteDrawProc, unless you want to use a RectDrawProc instead of the 
  54. automatically assigned ScaledMaskDrawProc. It will also change the DrawProc back to one
  55. of the standard BlitPixieMaskDrawProcs when you set the scaled size to -1 to turn off
  56. scaling. Here is a list of the available DrawProcs:
  57.  
  58.     // User DrawProcs:
  59. BlitPixie8BitScaledRectDrawProc
  60. BlitPixie16BitScaledRectDrawProc
  61.  
  62.     // Sprite DrawProcs:
  63. BP8BitScaledSpriteRectDrawProc
  64. BP8BitScaledSpriteMaskDrawProc
  65. BP16BitScaledSpriteRectDrawProc
  66. BP16BitScaledSpriteMaskDrawProc
  67.  
  68. The User DrawProcs are available for you to use directly if you want to do some direct
  69. scaling, such as scaling the contents of the work area as you copy it to the screen.
  70. The Sprite DrawProcs are what you should use when assigning a Sprite a scaling
  71. DrawProc. Do not get these two types of DrawProcs mixed up.
  72.  
  73.  
  74. -----------------------------------------------------------------------------
  75.  
  76. BlitPixieRotated.c
  77.  
  78.     These are blitters for rendering rotated versions of a sprite. The routines work
  79.     in 8-bit, 16-bits, and 32-bit. The API is simple. Use SWSetSpriteRotation to set
  80.     the sprite's rotation. The amount of rotation must be between 0 to the constant
  81.     kNumberOfRotationSteps.  Calling SWSetSpriteRotation with 0 as the rotation will
  82.     reset the sprite to use the standard blitting routines.
  83.     
  84.     Example Use:
  85.     
  86.     SWSetSpriteRotation(mySpritePtr, 3);  // Rotate it
  87.         
  88.     SWSetSpriteRotation(mySpritePtr, 0);  // Reset it back to normal
  89.     
  90.     
  91.     Note that all rotation is clipped to frameRect of the sprite.  In other words, the sprite
  92.     is rotated within its bounding rectangle.  Thus if you have a long skinny sprite, part
  93.     of it will be lost while rotating it.  The fix to this problem is to make sure that you 
  94.     store the sprite in the resource with enough white space around it that it can rotate 
  95.     fully and have nothing lost.
  96.     
  97.     Also note that rotation is done on-the-fly.  As a result, it can 
  98.     be fairly slow and the pixels in the frames don't match what shows up on the screen.  
  99.     This means that functions which rely on the sprite's mask, such as SWPixelCollision, 
  100.     won't work as expected.  Thus using the pixel or mask collisions routines with 
  101.     rotated sprites won't work accurately.
  102.     
  103.     Because blitting rotated sprites is slow and there are collision issues, there is 
  104.     a function called CreateRotatedFrameFromFrame that can be called to create a new 
  105.     frame object which contains a rotated version of a frame. In this way the frame is 
  106.     precomputed and blits quickly.  Example Use:
  107.     
  108.     for (currentRotation = 1; currentRotation < 8; currentRotation++) 
  109.         CreateRotatedFrameFromFrame(gSpriteWorld, 
  110.                                     myFrames[0], 
  111.                                     &myFrames[currentRotation], 
  112.                                     currentRotation);
  113.     
  114.     Imagine an asteroids like game with a single ship image.  This would fill up a frame
  115.     array with rotated versions of the ship stored in frame zero. 
  116.     
  117.     One additional note.  We need the sin and cos function to do this rotation.  For speed
  118.     we precompute the values of sin and cos corresponding to each amount of rotation.
  119.     Since we often want to use 8, 16, 32, or 64 degrees of rotations, arrays of these
  120.     are predefined in our code.  
  121.     
  122.     If we wish to use a different number for kNumberOfRotationSteps, then we need to 
  123.     uncomment the #define DYNAMICALLY_GENERATE_TABLE in the header file for this code.
  124.     When DYNAMICALLY_GENERATE_TABLE is defined, we have to call InitializeRotationTables() 
  125.     to fill up the tables with values.  This requires including MathLib.  If this
  126.     sounds confusing, just leave kNumberOfRotationSteps with the value 8, 16, 32, or 64.
  127.  
  128. ----------------------------------------------------------------------------- 
  129.  
  130. SWTranslucentBlitters.c
  131.  
  132. Routines for blitting translucent sprites in 8 bit or in 16 bit mode.  Both versions
  133. require a lookup table to work properly.  These lookup tables need to be initialized
  134. before being used.  To initialize the 16 bit version, call 
  135.  
  136. err = SWCreate16BitTranslucencyTable();
  137.  
  138. This creates a table which supports 30 levels of translucency and is small.  The 8-bit 
  139. table is much bigger.  It requires 256 * 256 bytes (or 64K) of memory for each level
  140. of translucency.  It also takes a relatively long time to compute.  For this reason
  141. we have a number of functions to allow creating these tables in advance and saving them
  142. in the resource fork so they can be loaded quickly.  By default you can call:
  143.  
  144. err = SWLoadOrCreate8BitTranslucencyTable(numLevelsOfTranslucency);
  145.  
  146. This single purpose function will try and load the table from a resource.  If it
  147. does not exist, it will create the table and save it to the resource fork before continuing.
  148. This means that the first time you run the program, it will be slow and will compute
  149. this and save it.  Next time you run the program it can just load it and thus will
  150. start up quickly.  Note that you can go into ResEdit and copy a TTAB resource that
  151. has been computed and paste it into your project's resource file.  This way, it will 
  152. automatically be copied into your application's resource fork at link timeand therefore 
  153. will never have to be computed.  (To reiterate, you run your program first. This 
  154. generates the computed table and stores it in the TTAB resource.  You copy this resource 
  155. into your project's resource file.  From then on this TTAB will get copied to your 
  156. application so you won't have to wait for it to be computed each time you recompile 
  157. and run.)
  158.  
  159. More detailed functions for manipulating these tables exist.  See the source code
  160. for more details in the comments.
  161.  
  162.  
  163. Once you've called initialized the table or tables, you can set a Sprite's translucency
  164. level with:
  165.  
  166. SWSetSpriteTranslucencyLevel(mySpritePtr, 6)
  167.  
  168. where mySpritePtr is a SpritePtr and 6 is a byte specifying the translucency level.
  169. This level is a number from 1 to the number of Levels, where 1 is barely
  170. visible and a higher number is more opaque.  If a level of any other value (e.g. 0
  171. or >= number of levels)    is specified, the Sprite is considered fully opaque and is 
  172. thus blitted normally. SWSetSpriteTranslucencyLevel automatically sets the Sprite's DrawProc to one of the translucent blitters.
  173.  
  174. You can find a sprite's level of translucency with 
  175.  
  176. SWGetSpriteTranslucencyLevel(mySpritePtr)
  177.  
  178. which will return the level as a byte, or 0 if the sprite is opaque.
  179.  
  180. IMPORTANT: The translucent blitters and idle Sprites do not mix! This means that each
  181. translucent Sprite should have a MoveProc or FrameProc that is called every frame that
  182. sets the Sprite's needsToBeDrawn flag to true.
  183.  
  184. -----------------------------------------------------------------------------
  185.  
  186. SWLightingSquares.c
  187.  
  188.  ** N.B. These functions are still relatively experimental.  They work fine, but the public API needs work to achieve better effects and uses.
  189.  
  190. These routines are for an alternative style of getting lighting effects.  It's main function is a Screen Blitting procedures that takes the offscreen work area and colors it as it copies it on screen.  Thus the parts copied on screen can  be made darker or lighter or a little reddish, etc.  
  191.  
  192. To support a feeling of lights, we divide the screen into a map of tiny squares  and associate a color and a level with each square.  As we blit onto the screen, we use this map to color the image.  The result is that the screen image looks nicely colorized.  Imagine each square having a colored gel placed over top of  it.
  193.  
  194. The smaller the squares in our map, the finer the grain of lighting but the greater the overhead.  More space and speed are required.  We also provide routines for setting  and managing this lighting map, including setting light levels and combining  lights (so blue lights and yellow lights will become greenish lights as they overlap).
  195.  
  196. These functions make use of the translucency table functions found in  "SWTranslucentBlitters.c" and therefore that file needs to be present for this to work.
  197.  
  198. Use SWInitializeLightingSquares(spriteWorldPtr, 8); to initialize the use of squares. 8 in this case is the size of the squares in pixels.  
  199.  
  200. Use:     
  201.  
  202. SWSetLightingSquare(spriteWorldPtr, col, row, color, opacity,                          
  203.                     relativeP, makeDirtyP); 
  204.  
  205. to set a cell's value.  Opacity is the translucency levels (as in the translucent blitters). relativeP is a boolean specifying whether to set the color and level directly or to blend it together with what is already in the cell.   makeDirtyP forces sprite world to redraw that cell on the screen during the next draw loop.
  206.  
  207. Use:     
  208.  
  209. SWLightUpArea (spriteWorldPtr, col, row,                  
  210.                   color,  level                         
  211.                bigLightP); 
  212.  
  213. to light up an area around a cell.  This is good for spotlights.  bigLightP makes the light really big.  Note that this just calls     SWSetLightingSquare repeatedly.        
  214.  
  215. SWDarkenLightingSquares (spriteWorldPtr); will blend black into every square in the grid to darken everything.  This is a good example of how to achieve a lighting effect with these squares.
  216.  
  217. Use 
  218.  
  219. SWExitLightingSquares (); 
  220.  
  221. to free up the tables when quitting.  
  222.  
  223. You may use these routines in a scrolling game, provided that you scroll in 
  224. multiples of the lighting grid.
  225.  
  226. The Lit Breakout Demo is an example of how to use these functions in an app.
  227.  
  228. -----------------------------------------------------------------------------
  229.  
  230. SWTinting.c
  231.  
  232. - Functions for tinting SpriteWorld graphics a particular color.   
  233. - Functions for using tinting to implement basic lighting techniques on           
  234.         sprites and tiles.
  235.  
  236. This style of lighting works well with tiles with a single kind of light.  This is because we precompute all of the sprites and tiles at the different light levels.  This makes it fast, but not very flexible.  See "SWLightingSquares.c" for another approach to lighting which is slightly slower, but is dynamic and handles an arbitrary number of colored lights.
  237.  
  238. Functionality documented above each function.  See the Lighting Demo for a representative example of how to use everything.
  239.  
  240. -----------------------------------------------------------------------------
  241.  
  242.  
  243. This is all provided as is with no promises or guarantees.  Don't count on me for support, service, or coherency.  And don't blame anyone else for my mistakes.  Thanks are always appreciated.  Drop me a line if this stuff is useful.
  244.